
package com.jf.cloud.supplier.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.BooleanUtil;
import cn.hutool.core.util.PhoneUtil;
import cn.hutool.core.util.StrUtil;
import com.jf.cloud.api.auth.bo.UserInfoInTokenBO;
import com.jf.cloud.api.auth.constant.SysTypeEnum;
import com.jf.cloud.api.auth.dto.AuthAccountDTO;
import com.jf.cloud.api.auth.feign.AccountFeignClient;
import com.jf.cloud.api.auth.vo.AuthAccountVO;
import com.jf.cloud.api.biz.feign.NotifyFeignClient;
import com.jf.cloud.api.leaf.feign.SegmentFeignClient;
import com.jf.cloud.api.rbac.dto.UserRoleDTO;
import com.jf.cloud.api.rbac.feign.UserRoleFeignClient;
import com.jf.cloud.common.constant.*;
import com.jf.cloud.common.database.dto.PageDTO;
import com.jf.cloud.common.database.util.PageUtil;
import com.jf.cloud.common.database.vo.PageVO;
import com.jf.cloud.common.exception.LuckException;
import com.jf.cloud.common.response.ResponseEnum;
import com.jf.cloud.common.response.ServerResponseEntity;
import com.jf.cloud.common.security.AuthUserContext;
import com.jf.cloud.common.util.IpHelper;
import com.jf.cloud.supplier.dto.SupplierUserDTO;
import com.jf.cloud.supplier.dto.SupplierUserRegisterDTO;
import com.jf.cloud.supplier.mapper.SupplierUserMapper;
import com.jf.cloud.supplier.model.SupplierUser;
import com.jf.cloud.supplier.service.SupplierUserService;
import com.jf.cloud.supplier.vo.SupplierUserVO;
import io.seata.spring.annotation.GlobalTransactional;
import ma.glasnost.orika.MapperFacade;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 供应商用户
 *
 * @author zz
 * @date 2022-03-14 17:04:32
 */
@Service
public class SupplierUserServiceImpl implements SupplierUserService {

    @Resource
    private SupplierUserMapper supplierUserMapper;
    @Autowired
    private AccountFeignClient accountFeignClient;
    @Autowired
    private UserRoleFeignClient userRoleFeignClient;
    @Autowired
    private MapperFacade mapperFacade;
    @Autowired
    private NotifyFeignClient notifyFeignClient;
    @Autowired
    private SegmentFeignClient segmentFeignClient;
    @Value("${jfcloud.expose.operation.auth:}")
    private Boolean permission;

    @Override
    public PageVO<SupplierUserVO> pageBySupplierId(PageDTO pageDTO, SupplierUserDTO supplierUserDTO) {
        PageVO<SupplierUserVO> page = PageUtil.doPage(pageDTO, () -> supplierUserMapper.listBySupplierId(supplierUserDTO));
        List<Long> userIds = page.getList().stream().map(SupplierUserVO::getSupplierUserId).collect(Collectors.toList());
        Integer sysType = Objects.equals(supplierUserDTO.getSupplierId(), Constant.PLATFORM_SHOP_ID) ? SysTypeEnum.PLATFORM.value() : SysTypeEnum.SUPPLIER.value();
        ServerResponseEntity<List<AuthAccountVO>> responseEntity = accountFeignClient.listUserByUserIdsAndType(userIds, sysType);
        Map<Long, AuthAccountVO> authAccountMap = responseEntity.getData().stream().collect(Collectors.toMap(AuthAccountVO::getUserId, a -> a));
        for (SupplierUserVO supplierUserVO : page.getList()) {
            AuthAccountVO authAccountVO = authAccountMap.get(supplierUserVO.getSupplierUserId());
            if (Objects.isNull(authAccountVO)) {
                continue;
            }
            supplierUserVO.setStatus(authAccountVO.getStatus());
            supplierUserVO.setUsername(authAccountVO.getUsername());
            supplierUserVO.setIsAdmin(authAccountVO.getIsAdmin());
            if (BooleanUtil.isFalse(permission) && StrUtil.isNotBlank(supplierUserVO.getPhoneNum())){
                supplierUserVO.setPhoneNum(PhoneUtil.hideBetween(supplierUserVO.getPhoneNum()).toString());
            }
        }
        return page;
    }

    @Override
    public SupplierUserVO getByUserId(Long userId) {
        SupplierUserVO supplierUser = supplierUserMapper.getByUserId(userId);
        ServerResponseEntity<List<Long>> roleIds = userRoleFeignClient.getRoleIds(supplierUser.getSupplierUserId());
        supplierUser.setRoleIds(roleIds.getData());
        ServerResponseEntity<AuthAccountVO> accountResponse = accountFeignClient.getByUserIdAndSysType(userId, AuthUserContext.get().getSysType());
        if (!accountResponse.isSuccess()) {
            throw new LuckException(accountResponse.getMsg());
        }
        AuthAccountVO data = accountResponse.getData();
        if (Objects.nonNull(data)) {
            mapperFacade.map(data, supplierUser);
        }
        return supplierUser;
    }

    @Override
    public SupplierUserVO getSimpleByUserId(Long userId) {
        return supplierUserMapper.getByUserId(userId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void save(SupplierUser supplierUser, List<Long> roleIds) {
        supplierUser.setSupplierUserId(segmentFeignClient.getSegmentId(DistributedIdKey.MALL4CLOUD_SUPPLIER_USER).getData());
        supplierUserMapper.save(supplierUser);
        if (CollUtil.isEmpty(roleIds)) {
            return;
        }
        UserRoleDTO userRoleDTO = new UserRoleDTO();
        userRoleDTO.setRoleIds(roleIds);
        userRoleDTO.setUserId(supplierUser.getSupplierUserId());
        userRoleFeignClient.saveByUserIdAndSysType(userRoleDTO);
    }

    @Override
    @GlobalTransactional(rollbackFor = Exception.class)
    @Transactional(rollbackFor = Exception.class)
    public void update(SupplierUser supplierUser, List<Long> roleIds) {
        UserRoleDTO userRoleDTO = new UserRoleDTO();
        userRoleDTO.setRoleIds(roleIds);
        userRoleDTO.setUserId(supplierUser.getSupplierUserId());
        userRoleDTO.setSysType(SysTypeEnum.SUPPLIER.value());
        supplierUserMapper.update(supplierUser);
        userRoleFeignClient.updateByUserIdAndSysType(userRoleDTO);
    }

    @Override
    @GlobalTransactional(rollbackFor = Exception.class)
    @Transactional(rollbackFor = Exception.class)
    public void deleteById(Long supplierUserId) {
        ServerResponseEntity<Void> responseEntity = accountFeignClient.deleteByUserIdAndSysType(supplierUserId);
        if (!responseEntity.isSuccess()) {
            throw new LuckException(responseEntity.getMsg());
        }
        userRoleFeignClient.deleteByUserIdAndSysType(supplierUserId);
        supplierUserMapper.deleteById(supplierUserId);
    }

    @Override
    public Long getUserIdBySupplierId(Long supplierId) {
        return supplierUserMapper.getUserIdBySupplierId(supplierId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @GlobalTransactional(rollbackFor = Exception.class)
    public void register(SupplierUserRegisterDTO supplierUserRegisterDTO) {
        // 校验注册信息
        this.checkRegisterInfo(supplierUserRegisterDTO);
        // 商家端用户表保存商家信息
        SupplierUser supplierUser = new SupplierUser();
        supplierUser.setSupplierUserId(segmentFeignClient.getSegmentId(DistributedIdKey.MALL4CLOUD_SUPPLIER_USER).getData());
        supplierUser.setNickName(supplierUserRegisterDTO.getUsername());
        supplierUser.setPhoneNum(supplierUserRegisterDTO.getMobile());
        supplierUser.setHasAccount(1);
        supplierUser.setSupplierId(Constant.DEFAULT_SUPPLIER_ID);
        supplierUserMapper.save(supplierUser);
        // 账号表保存商家信息
        AuthAccountDTO authAccountDTO = new AuthAccountDTO();
        authAccountDTO.setPhone(supplierUserRegisterDTO.getMobile());
        authAccountDTO.setPassword(supplierUserRegisterDTO.getPassword().trim());
        authAccountDTO.setStatus(StatusEnum.ENABLE.value());
        authAccountDTO.setCreateIp(IpHelper.getIpAddr());
        authAccountDTO.setSysType(SysTypeEnum.SUPPLIER.value());
        authAccountDTO.setUserId(supplierUser.getSupplierUserId());
        authAccountDTO.setIsAdmin(UserAdminType.ADMIN.value());
        authAccountDTO.setTenantId(Constant.DEFAULT_SHOP_ID);
        authAccountDTO.setIsPassShop(IsPassShopEnum.NO.value());
        authAccountDTO.setUsername(supplierUserRegisterDTO.getUsername());
        ServerResponseEntity<Long> saveAccountRes = accountFeignClient.save(authAccountDTO);
        if (!saveAccountRes.isSuccess()) {
            throw new LuckException(saveAccountRes.getMsg());
        }
    }

    @Override
    public ServerResponseEntity<Boolean> verifySupplierUserAccount(SupplierUserDTO supplierUserDTO) {
        // 账号表商家信息
        AuthAccountDTO authAccountDTO = new AuthAccountDTO();
        authAccountDTO.setPhone(supplierUserDTO.getPhone());
        authAccountDTO.setEmail(supplierUserDTO.getEmail());
        authAccountDTO.setUsername(supplierUserDTO.getUsername());
        authAccountDTO.setSysType(SysTypeEnum.SUPPLIER.value());
        authAccountDTO.setUserId(supplierUserDTO.getSupplierUserId());
        return accountFeignClient.verifyAccount(authAccountDTO);
    }

    @Override
    @GlobalTransactional(rollbackFor = Exception.class)
    @Transactional(rollbackFor = Exception.class)
    public void saveAccount(SupplierUserDTO supplierUserDTO) {
        SupplierUser supplierUser = mapperFacade.map(supplierUserDTO, SupplierUser.class);
        supplierUser.setSupplierId(supplierUserDTO.getSupplierId());
        supplierUser.setHasAccount(1);
        supplierUser.setPhoneNum(supplierUserDTO.getPhone());
        // 保存店铺职工信息
        this.save(supplierUser,supplierUserDTO.getRoleIds());
        Long supplierUserId = supplierUser.getSupplierUserId();
        // 账号表商家职工信息
        AuthAccountDTO authAccountDTO = new AuthAccountDTO();
        authAccountDTO.setCreateIp(IpHelper.getIpAddr());
        authAccountDTO.setPhone(supplierUserDTO.getPhone());
        authAccountDTO.setEmail(supplierUserDTO.getEmail());
        authAccountDTO.setUsername(supplierUserDTO.getUsername());
        authAccountDTO.setSysType(AuthUserContext.get().getSysType());
        authAccountDTO.setUserId(supplierUserId);
        authAccountDTO.setTenantId(supplierUser.getSupplierId());
        authAccountDTO.setStatus(supplierUserDTO.getStatus());
        authAccountDTO.setPassword(supplierUserDTO.getPassword());
        authAccountDTO.setIsPassShop(IsPassShopEnum.YES.value());
        authAccountDTO.setIsAdmin(0);
        ServerResponseEntity<Long> accountResponseEntity = accountFeignClient.save(authAccountDTO);
        if (!accountResponseEntity.isSuccess()) {
            throw new LuckException(accountResponseEntity.getMsg());
        }
    }

    @Override
    public Integer countAccoutByMobile(String mobile) {
        return supplierUserMapper.countAccoutByMobile(mobile);

    }

    @Override
    @GlobalTransactional(rollbackFor = Exception.class)
    @Transactional(rollbackFor = Exception.class)
    public void updateAccount(SupplierUserDTO supplierUserDTO) {
        // 修改店铺职工信息
        SupplierUser supplierUser = mapperFacade.map(supplierUserDTO, SupplierUser.class);
        supplierUser.setPhoneNum(supplierUserDTO.getPhone());
        supplierUser.setHasAccount(null);
        this.update(supplierUser, supplierUserDTO.getRoleIds());
        AuthAccountDTO authAccountDTO = mapperFacade.map(supplierUserDTO, AuthAccountDTO.class);
        UserInfoInTokenBO userInfoInTokenBO = AuthUserContext.get();
        authAccountDTO.setSysType(userInfoInTokenBO.getSysType());
        authAccountDTO.setTenantId(userInfoInTokenBO.getTenantId());
        authAccountDTO.setUserId(supplierUserDTO.getSupplierUserId());
        // 修改店铺account信息
        ServerResponseEntity<Void> serverResponseEntity = accountFeignClient.update(authAccountDTO);
        if (!serverResponseEntity.isSuccess()) {
            throw new LuckException(serverResponseEntity.getMsg());
        }

    }

    /**
     * 校验注册信息
     * @param supplierUserRegisterDTO
     * @return
     */
    public void checkRegisterInfo(SupplierUserRegisterDTO supplierUserRegisterDTO) {
        // 用户名
        ServerResponseEntity<Integer> usernameRes = accountFeignClient.countByUserNameAndSysType(supplierUserRegisterDTO.getUsername(), SysTypeEnum.SUPPLIER.value());
        if (!usernameRes.isSuccess()) {
            throw new LuckException("服务器繁忙！");
        }
        if (usernameRes.getData() > 0) {
            throw new LuckException("用户名已经存在");
        }
        // 手机号验证码
        ServerResponseEntity<Integer> mobileRes = accountFeignClient.countByMobileAndSysType(supplierUserRegisterDTO.getMobile(), SysTypeEnum.SUPPLIER.value());
        if (!mobileRes.isSuccess()) {
            throw new LuckException("服务器繁忙!");
        }
        if (mobileRes.getData() > 0) {
            throw new LuckException("该手机号已经被注册");
        }
        ServerResponseEntity<Boolean> sendNotifyResponse = notifyFeignClient.checkValidCode(supplierUserRegisterDTO.getMobile(), supplierUserRegisterDTO.getValidCode(), SendTypeEnum.VALID);
        Boolean data = sendNotifyResponse.getData();
        if (Objects.equals(sendNotifyResponse.getCode(), ResponseEnum.OK.value()) && Objects.nonNull(data) && !data) {
            throw new LuckException("验证码有误或已过期");
        }
    }

}
